package com.googlecode.spreadit.matching;

import java.io.Serializable;

import com.googlecode.spreadit.bean.Message;

/**
 * This is the abstract super-class of all n-ary match expressions and therefore
 * follows the <a href="http://en.wikipedia.org/wiki/Composite_pattern>composite
 * pattern</a>.
 * 
 * This class implements a fluent API (see e.g. <a
 * href="http://en.wikipedia.org/wiki/Fluent_interface#Java"
 * >http://en.wikipedia.org/wiki/Fluent_interface#Java</a>) in conjunction with
 * other classes in this package (i.e., {@link MessageField}, {@link MatchField}
 * ).
 * 
 * @author Markus L. Dechert (markus.dechert@googlemail.com)
 */
abstract public class MatchExpression implements Serializable {

	private static final long serialVersionUID = -4001448679951281936L;

	abstract public boolean matches(Message m);

	//
	// Fluent API for the matching
	// (binary operators)
	//
	public static MatchTwo and(MatchExpression... expressions) {
		return binaryOp(Relation.AND, expressions);
	}

	public static MatchTwo or(MatchExpression... expressions) {
		return binaryOp(Relation.OR, expressions);
	}

	public static MatchTwo xor(MatchExpression... expressions) {
		return binaryOp(Relation.EITHER_OR, expressions);
	}

	private static MatchTwo binaryOp(Relation op,
			MatchExpression... expressions) {
		if (expressions.length < 2) {
			throw new IllegalArgumentException(op.name()
					+ " can only be used with two or more arguments");
		}

		MatchTwo result = new MatchTwo(expressions[0], expressions[1], op);
		for (int i = 2; i < expressions.length; i++) {
			result = new MatchTwo(result, expressions[i], op);
		}
		return result;
	}

}